#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "spreadsheet.h"
#include "gotocelldialog.h"
#include "finddialog.h"
#include "sortdialog.h"

#include<QtWidgets>
/* why??????????????
 * （1）if(!dialog.exec())    //为什么添加一个！成功了
 * 因为设置槽时，将ok按钮链接到reject()返回0
 * （2）为什么手动连接信号和槽，exec()返回1，但QT设计师中却返回0
 *  %$%$%$………………发现神器，qDebug()<<output1<<output2;实现控制台输出信息
 *
 *
 * 1.如何弹出对话框，消息框
 * 2.消息框格式
 *      QMessageBox::warning(parent,title,message,buttons);
 * 3.toggled和trigger区别
    toggle在实物上有开关的意思，在两个状态间进行转换。在Qt中，checkable按纽或是图标的槽
函数应该用toggled()事件来激活，
     trigger更有触发的意思。这个单词还有另一个意思就是板机，枪械上用来发射子弹的那种。
我们很容易想到板机是没有开/关两种状态的在Qt中，一般的按纽（uncheckable）的激活方式即是triggered()。
    4.事件和信号槽的关系
    信号通过事件实现，事件可以过滤，事件更底层，事件是基础，信号是扩展。
    5.使用ctrl+鼠标左键跳转到cpp
*/
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    spreadsheet=new Spreadsheet;
    setCentralWidget(spreadsheet);
    createStatusBar();
    connectActions();
    setCurrentFile("");

    createRecentFileActions();
    createRecentFileMenus();    //先创建action,再添加到菜单里，顺序不能乱
    createContextMenu();

    findDialog=0;
    readSettings();
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::createContextMenu()
{
    spreadsheet->addAction(ui->action_Cut);
    spreadsheet->addAction(ui->action_Copy);
    spreadsheet->addAction(ui->action_Paste);
    spreadsheet->setContextMenuPolicy(Qt::ActionsContextMenu);
}

void MainWindow::readSettings()
{
    QSettings settings("Software Inc.","Speadsheet");
    restoreGeometry(settings.value("geometry").toByteArray());
    bool showGrid=settings.value("showGrid",true).toBool();
    ui->action_Show_Grid->setChecked(showGrid);

    recentFiles=settings.value("recentFiles").toStringList();
    updateRecentFileActions();
    bool autoRecalc=settings.value("autoRecalc",true).toBool();
    ui->action_Auto_Recalculate->setChecked(autoRecalc);
}

void MainWindow::writeSettings()
{
    QSettings settings("Software Inc.","Speadsheet");
    settings.setValue("geometry",saveGeometry());
    settings.setValue("showGrid",ui->action_Show_Grid->isChecked());
    settings.setValue("autoRecalc",ui->action_Auto_Recalculate->isChecked());
    settings.setValue("recentFiles",recentFiles);
}

void MainWindow::connectActions()
{
    connect(ui->action_About_QT,SIGNAL(triggered()),qApp,SLOT(aboutQt()));
    connect(ui->actionAbout,SIGNAL(triggered()),this,SLOT(about()));
    connect(ui->actionEixt,SIGNAL(triggered()),this,SLOT(close()));
    connect(ui->actionOpen,SIGNAL(triggered()),this,SLOT(open()));
    connect(ui->action_Save,SIGNAL(triggered()),this,SLOT(save()));
    connect(ui->actionSave_As,SIGNAL(triggered()),this,SLOT(saveAs()));
    connect(ui->action_New,SIGNAL(triggered()),this,SLOT(newFile()));
    connect(ui->action_GotoCell,SIGNAL(triggered()),this,SLOT(gotoCell()));

    connect(ui->action_Cut,SIGNAL(triggered()),spreadsheet,SLOT(cut()));
    connect(ui->action_Copy,SIGNAL(triggered()),spreadsheet,SLOT(copy()));
    connect(ui->action_Delete,SIGNAL(triggered()),spreadsheet,SLOT(del()));
    connect(ui->action_Paste,SIGNAL(triggered()),spreadsheet,SLOT(paste()));
    connect(ui->actionRow,SIGNAL(triggered()),spreadsheet,SLOT(selectCurrentRow()));
    connect(ui->actionColumn,SIGNAL(triggered()),spreadsheet,SLOT(selectCurrentColumn()));
    connect(ui->actionAll,SIGNAL(triggered()),spreadsheet,SLOT(selectAll()));
    connect(ui->action_Recalculate,SIGNAL(triggered()),spreadsheet,SLOT(recalculate()));
    connect(ui->action_Auto_Recalculate,SIGNAL(triggered(bool)),spreadsheet,SLOT(setAutoRecalculate(bool)));
    connect(ui->action_Show_Grid,SIGNAL(triggered(bool)),spreadsheet,SLOT(setShowGrid(bool)));
    connect(ui->action_Find,SIGNAL(triggered()),this,SLOT(find()));
    connect(ui->action_Sort,SIGNAL(triggered()),this,SLOT(sort()));
}
void MainWindow::sort()
{
    SortDialog dialog(this);
    QTableWidgetSelectionRange range=spreadsheet->selectedRange();
    dialog.setColumnRange('A'+range.leftColumn(),'A'+range.rightColumn());
    if(dialog.exec())
    {
        SpreadsheetCompare compare;
        compare.keys[0]=dialog.getPrimaryColumnCombo()->currentIndex();
        compare.keys[1]=dialog.getSecondaryColumnCombo()->currentIndex()-1;
        compare.keys[2]=dialog.getTertiaryColumnCombo()->currentIndex()-1;
        compare.ascending[0]=(dialog.getPrimaryOrderCombo()->currentIndex()==0);
        compare.ascending[1]=(dialog.getSecondaryOrderCombo()->currentIndex()==0);
        compare.ascending[2]=(dialog.getTertiaryOrderCombo()->currentIndex()==0);

        spreadsheet->sort(compare);
    }
}

void MainWindow::find()
{
    if(!findDialog)
    {
        findDialog=new FindDialog(this);
        connect(findDialog,SIGNAL(findNext(QString,Qt::CaseSensitivity)),
                spreadsheet,SLOT(findNext(QString,Qt::CaseSensitivity)));
        connect(findDialog,SIGNAL(findPrevious(QString,Qt::CaseSensitivity)),
                spreadsheet,SLOT(findPrevious(QString,Qt::CaseSensitivity)));
    }
    findDialog->show();
    findDialog->raise();
    findDialog->activateWindow();
}

void MainWindow::gotoCell()
{
    GotoCellDialog dialog(this);
    statusBar()->showMessage("abc",2000);

//    int flag=dialog.exec();
//    qDebug()<<flag;
    if(dialog.exec())              //ok按钮连接reject()为什么添加一个！成功了
    {
        statusBar()->showMessage("HELLO",2000);
//        qDebug()<<flag;
//            statusBar()->showMessage(QString(flag),2000);
        QString str=dialog.getCellLocation().toUpper();
        spreadsheet->setCurrentCell(str.mid(1).toInt()-1,str[0].unicode()-'A');

    }


}

void MainWindow::newFile()
{
   if(okToContinue())
   {
       spreadsheet->clear();
       setCurrentFile("");
   }
}

void MainWindow::openRecentFile()
{
   if(okToContinue())
   {
      QAction* action=qobject_cast<QAction*>(sender());
        if(action)
            loadFile(action->data().toString());

   }
}

void MainWindow::createRecentFileActions()
{
    for(int i=0;i<MaxRecentFiles;++i)
    {
        recentFileActions[i]=new QAction(this);
        recentFileActions[i]->setText("xxxx");
        recentFileActions[i]->setVisible(true);
        connect(recentFileActions[i],SIGNAL(triggered()),this,SLOT(openRecentFile()));
    }
}
void MainWindow::createRecentFileMenus()     //插入到菜单中
{
    for(int i=0;i<MaxRecentFiles;++i)
    {
        ui->menu_File->insertAction(ui->actionEixt,recentFileActions[i]);
    }
    separatorAction=ui->menu_File->insertSeparator(ui->actionEixt);
}
void MainWindow::updateRecentFileActions()
{
    QMutableStringListIterator i(recentFiles);
    while(i.hasNext())
    {
        if(!QFile::exists(i.next()))
            i.remove();
    }
    for(int j=0;j<MaxRecentFiles;++j)
    {
        if(j<recentFiles.count())
        {
            QString text=tr("%1 %2").arg(j+1).arg(strippedName(recentFiles[j]));
            recentFileActions[j]->setText(text);
            recentFileActions[j]->setVisible(true);
            recentFileActions[j]->setData(recentFiles[j]);
        }else{
            recentFileActions[j]->setVisible(false);
        }
    }
    separatorAction->setVisible(!recentFiles.isEmpty());
}

bool MainWindow::save()
{
    if(curFile.isEmpty())
    {
        return saveAs();
    }else{
        return saveFile(curFile);
    }
}
bool MainWindow::saveAs()
{
    QString fileName = QFileDialog::getSaveFileName(this,
                               tr("Save Spreadsheet"), ".",
                               tr("Spreadsheet files (*.sp)"));
    if (fileName.isEmpty())
        return false;

    return saveFile(fileName);
}
bool MainWindow::saveFile(const QString &fileName)
{
    if(!spreadsheet->writeFile(fileName))
    {
        statusBar()->showMessage(tr("Saving canceled"),2000);
        return false;
    }
    setCurrentFile(fileName);
    statusBar()->showMessage(tr("File saved"),2000);
    return true;
}

void MainWindow::open()
{
    QString fileName=QFileDialog::getOpenFileName(this,tr("Open"),".",
                                                  tr("Spreadsheet files(*.sp)"));
    if(!fileName.isEmpty())
        loadFile(fileName);
}
bool MainWindow::loadFile(const QString &fileName)
{
    if(!spreadsheet->readFile(fileName))
    {
        statusBar()->showMessage(tr("Loading canceled"),2000); //显示2秒
        return false;
    }
    setCurrentFile(fileName);
    statusBar()->showMessage(tr("File loaded"),2000);
    return true;
}
void MainWindow::setCurrentFile(const QString &fullFileName)
{
    curFile=fullFileName;      //路径名
    setWindowModified(false);

    QString shownName=tr("Untitiled");
    if(!curFile.isEmpty())
    {
        shownName=strippedName(curFile);   //从路径名里提取文件名
        recentFiles.removeAll(curFile);
        recentFiles.prepend(curFile);
        updateRecentFileActions();
    }
    setWindowTitle(tr("%1[*]-%2").arg(shownName).arg(tr("Spreadsheet")));

}
QString MainWindow::strippedName(const QString &fullFileName)
{
    return QFileInfo(fullFileName).fileName();
}

void MainWindow::about()
{
    QMessageBox::about(this,tr("About SpreadSheet"),
                       tr("<h2>SpreadSheet 1.1</h2>"
                          "<p>Copyright &copy; RV Software Inc")
                       );
}
bool MainWindow::okToContinue()
{
    if(isWindowModified())
    {
        int r=QMessageBox::warning(this,tr("SpreadSheet"),
                             tr("^~^"),
                            QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel);
        if(r==QMessageBox::Yes)
        {
            save();
            return true;
        }else if(r==QMessageBox::Cancel){
            return false;
        }
    }
    return true;
}

void MainWindow::closeEvent(QCloseEvent *event)
{
    if(okToContinue())
    {
        writeSettings();
        event->accept();
    }else{
        event->ignore();
    }
}
void MainWindow::updateStatusBar()
{
    locationLabel->setText(spreadsheet->currentLocation());
    formulaLabel->setText(spreadsheet->currentFormula());
}
void MainWindow::spreadsheetModified()
{
    setWindowModified(true);
    updateStatusBar();
}

void MainWindow::createStatusBar()
{
    locationLabel=new QLabel(tr("W999"));
    locationLabel->setAlignment(Qt::AlignHCenter);
    locationLabel->setMinimumSize(locationLabel->sizeHint());

    formulaLabel=new QLabel;
    formulaLabel->setIndent(3);

    ui->statusBar->addWidget(locationLabel);
    ui->statusBar->addWidget(formulaLabel);
    connect(spreadsheet,SIGNAL(currentCellChanged(int,int,int,int)),this,SLOT(updateStatusBar()));
    connect(spreadsheet,SIGNAL(modified()),this,SLOT(spreadsheetModified()));
    updateStatusBar();
}
